package com.lottery.controller;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lottery.dto.*;
import com.lottery.pojo.*;
import com.lottery.service.MachineService;
import com.lottery.service.OrderService;
import com.lottery.service.RegionService;
import com.lottery.service.SpecialNumberService;
import com.lottery.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
public class OrderController {
    @Autowired
    private OrderService orderService;

    /**
     * 分页查询orders集合
     * 1、[machine_number]localhost:8001/getOrders?page=1&pageSize=2&machine_number=188
     * 2、[machine_number+(startTime+endTime)]localhost:8001/getOrders?page=1&pageSize=2&machine_number=188&startTime=2021-05-24 02:50:27&endTime=2021-05-24 02:58:27
     * 3、[machine_number+serial_number+(startTime+endTime)]localhost:8001/getOrders?page=1&pageSize=2&machine_number=188&startTime=2021-05-24 02:50:27&endTime=2021-05-24 02:58:27&serial_number=1882021052300003
     * 4、[machine_number+(startTime+endTime)+is_winner]localhost:8001/getOrders?page=1&pageSize=2&machine_number=188&startTime=2021-05-24 02:50:27&endTime=2021-05-24 02:58:27&serial_number=1882021052300003&is_winner=0
     */
    @PostMapping("getOrders")
    public OrdersOutputDTO getOrders(
            @RequestParam(name = "bet_number", required = false) String bet_number,
            @RequestParam(name = "machine_number", required = false) String machine_number,
            @RequestParam(name = "serial_number", required = false) String serial_number,
            @RequestParam(name = "is_winner", required = false) Integer is_winner,
            //分页
            @RequestParam(name = "page", required = false, defaultValue = "0") int page,
            @RequestParam(name = "pageSize", required = false, defaultValue = "0") int pageSize,
            //日期
            @RequestParam(name = "startTime", required = false) String startTime,
            @RequestParam(name = "endTime", required = false) String endTime,
            //地区
            @RequestParam(name = "belong_to", required = false) String belong_to,
            //是否今天1是今天
            @RequestParam(name = "isToday", required = false) String isToday,
            @RequestParam(name = "b_is_winner", required = false) String b_is_winner,
            @RequestParam(name = "checked_winning", required = false) String checked_winning
    ) {
        if (startTime == null || startTime.contains("a") || !startTime.startsWith("20") || startTime.length() < 10) startTime = null;
        if (endTime == null || endTime.contains("a") || !endTime.startsWith("20") || endTime.length() < 10) endTime = null;
        if (serial_number == null || serial_number.equals("") || serial_number.equals("undefined")) serial_number = null;
        if (belong_to == null || belong_to.equals("") || belong_to.equals("undefined")) belong_to = null;

        //if (b_is_winner == null) b_is_winner = "0";
        //if (checked_winning == null) checked_winning = "0";

        if (isToday != null && isToday.equals("1")) {
            startTime = new SimpleDateFormat("yyyy-MM-dd").format(System.currentTimeMillis() - DateUtils.ONE_DAY_MILLIS);
            endTime = DateUtils.nowDate();
        }

        log.info("getOrders(), bet_number:" + bet_number + ", machine_number:" + machine_number + ", serial_number:" + serial_number + ", is_winner:" + is_winner + ", page:" + page + ", pageSize:" + pageSize + ", startTime:" + startTime + ", endTime:" + endTime + ", isToday:" + isToday + ", b_is_winner:" + b_is_winner + ", checked_winning:" + checked_winning + ", belong_to:" + belong_to);

        PageHelper.startPage(page, pageSize);
        PageInfo<OrdersAndBetNumbersDTO> pageInfo = new PageInfo<>(orderService.getOrders(bet_number, machine_number, serial_number, is_winner, startTime, endTime, belong_to, b_is_winner, checked_winning));

        OrdersOutputDTO outputDTO = new OrdersOutputDTO();
        List<OrdersAndBetNumbersDTO> infoList = pageInfo.getList();
//        double totalPrice = infoList.stream().mapToDouble(OrdersAndBetNumbersDTO::getBet_money).summaryStatistics().getSum();
        double totalPrice = orderService.getOrders(bet_number, machine_number, serial_number, is_winner, startTime, endTime, belong_to, b_is_winner, checked_winning).stream().mapToDouble(OrdersAndBetNumbersDTO::getBet_money).summaryStatistics().getSum();
        outputDTO.setTotalPrice(totalPrice);
        outputDTO.setPageCount(pageInfo.getPages());

        //同一序列号颜色标记==>
        String tempSerial = "";
        int tempCount = 0;
        for (OrdersAndBetNumbersDTO dto : infoList) {
            if (!dto.getSerial_number().equals(tempSerial)) {
                tempCount += 1;
                tempSerial = dto.getSerial_number();
            }
            dto.setColor(tempCount % 2 == 0 ? 0 : 1);
        }
        //<==

        //时间-4
        /*for (OrdersAndBetNumbersDTO dto : infoList) {
            dto.setCreated_at(DateUtils.subDTHours4(dto.getCreated_at()));
            dto.setUpdated_at(DateUtils.subDTHours4(dto.getUpdated_at()));
            dto.setDeleted_at(DateUtils.subDTHours4(dto.getDeleted_at()));
        }*/

        outputDTO.setOrderList(infoList);
        return outputDTO;
    }

    /**
     * 根据id删除orders记录
     * 1、[]localhost:8001/deleteOrderById?id=9998
     */
    @PostMapping("deleteOrderById")
    public SimpleOutputDTO<Boolean> deleteOrderById(int id) {
        SimpleOutputDTO<Boolean> outputDTO = new SimpleOutputDTO<>();
        outputDTO.setData(orderService.deleteOrderById(id) >= 0);
        return outputDTO;
    }

    /**
     * 根据流水号删除orders记录
     * 1、[]localhost:8001/deleteOrderBySerialNumber?serial_number=123211
     */
    @PostMapping("deleteOrderBySerialNumber")
    public SimpleOutputDTO<Boolean> deleteOrderBySerialNumber(String serial_number) {
        SimpleOutputDTO<Boolean> outputDTO = new SimpleOutputDTO<>();
        outputDTO.setData(orderService.deleteOrderBySerialNumber(serial_number) >= 0);
        return outputDTO;
    }

    @PostMapping("deleteOrderByDateRange")
    public void deleteOrderByDateRange(String startTime, String endTime) {
        orderService.deleteOrderByDateRange(startTime, endTime);
    }


    /**按照机号查找orders/bet_numbers/winning_histories表的价格和machines表的commission*/
    @Autowired
    private MachineService machineService;

    @PostMapping("getTotalCheck")
    public List<TotalCheckOutputDTO> getTotalCheck(String machineNumber, String startTime, String endTime) {
        List<TotalCheckOutputDTO> output = new ArrayList<>();

        List<TableMachines> machines = machineService.getMachines(machineNumber);
        for (TableMachines machine : machines) {
            TotalCheckOutputDTO totalCheckOutputDTO = new TotalCheckOutputDTO();
            totalCheckOutputDTO.setMachine_number(machine.getMachine_number());
            totalCheckOutputDTO.setCommission("" + machine.getCommission());
            String machine_number = machine.getMachine_number();
            //这个设备号对应的所有订单
            List<OrdersAndBetNumbersDTO> orderList = orderService.getOrdersByMachineNumber(machine_number, startTime, endTime);
            if (orderList != null && orderList.size() > 0) {
                double prizes = orderService.getPureBetNumbers(orderList).stream().mapToDouble(OrdersAndBetNumbersDTO::getPrizes).summaryStatistics().getSum();
                totalCheckOutputDTO.setB_prizes(prizes);
            }

            double totalWinningAmount = orderService.getPureOrders(machine_number, "", startTime, endTime).stream().mapToDouble(OrdersAndBetNumbersDTO::getTotal_winning_amount).summaryStatistics().getSum();
            totalCheckOutputDTO.setTotal_winning_amount(totalWinningAmount);
            output.add(totalCheckOutputDTO);
        }
        return output;
    }


    //------------------app
    @PostMapping("appGetOrders")
    public List<AppOrdersOutputDTO> appGetOrders(
            @RequestParam(name = "machine_number", required = false) String machine_number,
            @RequestParam(name = "serial_number", required = false) String serial_number,
            @RequestParam(name = "is_winner", required = false) Integer is_winner,
            @RequestParam(name = "startTime", required = false) String startTime,
            @RequestParam(name = "endTime", required = false) String endTime) {
        if (serial_number == null || serial_number.equals("") || serial_number.equals("undefined")) serial_number = null;
        /*List<AppOrdersOutputDTO> orders = orderService.appGetOrders(machine_number, serial_number, is_winner, startTime, endTime);
        for (AppOrdersOutputDTO dto : orders) {
            dto.setCreated_at(DateUtils.subDTHours4(dto.getCreated_at()));
            dto.setUpdated_at(DateUtils.subDTHours4(dto.getUpdated_at()));
            dto.setDeleted_at(DateUtils.subDTHours4(dto.getDeleted_at()));
        }
        return orders;*/
        return orderService.appGetOrders(machine_number, serial_number, is_winner, startTime, endTime);
    }

    @PostMapping("updateOrderPaid")
    public void updateOrderPaid(String id) {
        orderService.updateOrderPaid(id);
    }

    @Autowired
    private RegionService regionService;
    @Autowired
    private SpecialNumberService specialNumberService;
    private double tempExceeding = 0;//特殊号码超额

    @PostMapping("saveOrder")
    public SaveOrderOutputDTO saveOrder(@RequestBody SaveOrderInputDTO inputDTO) {
        //当前时间
        String dt = DateUtils.getSub4DT();

        SaveOrderOutputDTO outputDTO = new SaveOrderOutputDTO();
        //查找Orders表中serial_number=>返回600'Duplicated Serial Number';done
        OrdersOutputDTO orders = getOrders(null, null, inputDTO.getSerialNumber(), null, 1, 0, null, null, null, null, null, null);
        List<OrdersAndBetNumbersDTO> orderList = orders.getOrderList();
        log.info("saveOrder(), orderList:{}", JSON.toJSON(orderList));
        if (orderList != null && orderList.size() > 0) {
            outputDTO.setStatus(600);
            outputDTO.setMessage("Duplicated Serial Number!");
            return outputDTO;
        }

        //bets中同num的money相加=得到新的合并money的bets;done
        List<SaveOrderInputDTO.Bets> filterBets = new ArrayList<>();
        List<SaveOrderInputDTO.Bets> bets = inputDTO.getBets();
        for (SaveOrderInputDTO.Bets bet : bets) {
            if (bet.isPool()) {
                bet.setNum(bet.getNum() + " P");
            }
        }
        bets.parallelStream().collect(Collectors.groupingBy(SaveOrderInputDTO.Bets::getNum, Collectors.toList())).forEach(
                (integer, bets1) -> bets1.stream().reduce((o1, o2) -> new SaveOrderInputDTO.Bets(
                        o1.getSrcNumber(),
                        o1.getBelongTo(),
                        o1.getCreatedAt(),
                        o1.getIsWinner(),
                        o1.getMoney() + o2.getMoney(),
                        o1.getNum(),
                        o1.isPool(),
                        o1.getPrizes(),
                        o1.getRank(),
                        o1.getType())).ifPresent(filterBets::add)
        );
        inputDTO.setBets(filterBets);
        log.info("saveOrder(), after filterBets' inputDTO:{}", JSON.toJSON(inputDTO));

        //校验regions表中限额;done
        List<TableRegions> regions = regionService.getRegions();
        log.info("saveOrder(), regions:{}", JSON.toJSON(regions));
        String belongTo = inputDTO.getBelongTo();//入参属地
        //查询今天的4,3,2位订单
        List<TableBetNumbers> betsByDate = orderService.getBetsByDate(DateUtils.getSub4Date() + " 00:00:00", DateUtils.getSub4Date() + " 23:59:59", null);
        double has4total = betsByDate.stream().filter(tableBetNumbers -> !tableBetNumbers.getBet_number().contains("P") && tableBetNumbers.getBet_number().length() == 4).mapToDouble(TableBetNumbers::getBet_money).summaryStatistics().getSum();
        double has3total = betsByDate.stream().filter(tableBetNumbers -> !tableBetNumbers.getBet_number().contains("P") && tableBetNumbers.getBet_number().length() == 3).mapToDouble(TableBetNumbers::getBet_money).summaryStatistics().getSum();
        double has2total = betsByDate.stream().filter(tableBetNumbers -> !tableBetNumbers.getBet_number().contains("P") && tableBetNumbers.getBet_number().length() == 2).mapToDouble(TableBetNumbers::getBet_money).summaryStatistics().getSum();
        double has4PTotal = betsByDate.stream().filter(tableBetNumbers -> tableBetNumbers.getBet_number().contains("P") && tableBetNumbers.getBet_number().length() == 6).mapToDouble(TableBetNumbers::getBet_money).summaryStatistics().getSum();
        double has3PTotal = betsByDate.stream().filter(tableBetNumbers -> tableBetNumbers.getBet_number().contains("P") && tableBetNumbers.getBet_number().length() == 5).mapToDouble(TableBetNumbers::getBet_money).summaryStatistics().getSum();
        double has2PTotal = betsByDate.stream().filter(tableBetNumbers -> tableBetNumbers.getBet_number().contains("P") && tableBetNumbers.getBet_number().length() == 4).mapToDouble(TableBetNumbers::getBet_money).summaryStatistics().getSum();
        //入参bets中4,3,2位pool和非pool的总金额
        double pool4TotalMoney = bets.stream().filter(bet -> bet.isPool() && (bet.getNum() + "").length() == 4).collect(Collectors.toList()).stream().mapToDouble(SaveOrderInputDTO.Bets::getMoney).summaryStatistics().getSum();
        double pool3TotalMoney = bets.stream().filter(bet -> bet.isPool() && (bet.getNum() + "").length() == 3).collect(Collectors.toList()).stream().mapToDouble(SaveOrderInputDTO.Bets::getMoney).summaryStatistics().getSum();
        double pool2TotalMoney = bets.stream().filter(bet -> bet.isPool() && (bet.getNum() + "").length() == 2).collect(Collectors.toList()).stream().mapToDouble(SaveOrderInputDTO.Bets::getMoney).summaryStatistics().getSum();
        double notPool4TotalMoney = bets.stream().filter(bet -> !bet.isPool() && (bet.getNum() + "").length() == 4).collect(Collectors.toList()).stream().mapToDouble(SaveOrderInputDTO.Bets::getMoney).summaryStatistics().getSum();
        double notPool3TotalMoney = bets.stream().filter(bet -> !bet.isPool() && (bet.getNum() + "").length() == 3).collect(Collectors.toList()).stream().mapToDouble(SaveOrderInputDTO.Bets::getMoney).summaryStatistics().getSum();
        double notPool2TotalMoney = bets.stream().filter(bet -> !bet.isPool() && (bet.getNum() + "").length() == 2).collect(Collectors.toList()).stream().mapToDouble(SaveOrderInputDTO.Bets::getMoney).summaryStatistics().getSum();
        log.info("saveOrder(), 入参地区:{}, totalPool4:{},3:{},2:{}, limit4:{},3:{},2:{}", inputDTO.getBelongTo(), pool4TotalMoney, pool3TotalMoney, pool2TotalMoney, notPool4TotalMoney, notPool3TotalMoney, notPool2TotalMoney);
        for (int i = 0; i < regions.size(); i++) {//与表中额度比较
            int digit2_pool_limitK = regions.get(i).getDigit2_pool_limit();
            int digit3_pool_limitK = regions.get(i).getDigit3_pool_limit();
            int digit4_pool_limitK = regions.get(i).getDigit4_pool_limit();
            int digit2_limitK = regions.get(i).getDigit2_limit();
            int digit3_limitK = regions.get(i).getDigit3_limit();
            int digit4_limitK = regions.get(i).getDigit4_limit();
            log.info("saveOrder(), 库中地区:{}, pool4:{},3:{},2:{}, limit4:{},3:{},2:{}", regions.get(i).getRegion_name(), digit4_pool_limitK, digit3_pool_limitK, digit2_pool_limitK, digit4_limitK, digit3_limitK, digit2_limitK);
            if ((belongTo.contains("K") && i == 0) || (belongTo.contains("F") && i == 1) || (belongTo.contains("D") && i == 2) || (belongTo.contains("S") && i == 3)) {
                if (pool4TotalMoney + has4PTotal > digit4_pool_limitK) {return new SaveOrderOutputDTO(400, regions.get(i).getRegion_name() + " area's POOL4 exceeding the limit:" + (pool4TotalMoney + has4PTotal - digit4_pool_limitK));}
                if (pool3TotalMoney + has3PTotal > digit3_pool_limitK) {return new SaveOrderOutputDTO(400, regions.get(i).getRegion_name() + " area's POOL3 exceeding the limit:" + (pool3TotalMoney + has3PTotal - digit3_pool_limitK));}
                if (pool2TotalMoney + has2PTotal > digit2_pool_limitK) {return new SaveOrderOutputDTO(400, regions.get(i).getRegion_name() + " area's POOL2 exceeding the limit:" + (pool2TotalMoney + has2PTotal - digit2_pool_limitK));}
                if (notPool4TotalMoney + has4total > digit4_limitK) {return new SaveOrderOutputDTO(400, regions.get(i).getRegion_name() + " area's NOT POOL4 exceeding the limit:" + (notPool4TotalMoney + has4total - digit4_limitK));}
                if (notPool3TotalMoney + has3total > digit3_limitK) {return new SaveOrderOutputDTO(400, regions.get(i).getRegion_name() + " area's NOT POOL3 exceeding the limit:" + (notPool3TotalMoney + has3total - digit3_limitK));}
                if (notPool2TotalMoney + has2total > digit2_limitK) {return new SaveOrderOutputDTO(400, regions.get(i).getRegion_name() + " area's NOT POOL2 exceeding the limit:" + (notPool2TotalMoney + has2total - digit2_limitK));}
            }
        }

        //校验特殊号码限额;done
        List<TableSpecialNumbers> specialNumbers = specialNumberService.getSpecialNumbers();//根据此判断各地区自己设置的号码限额
        log.info("saveOrder(), specialNumbers:{}", JSON.toJSON(specialNumbers));
        List<TableSpecialNumbers> kNumbers = specialNumbers.stream().filter(tableSpecialNumbers -> tableSpecialNumbers.getRegion_id() == 1).collect(Collectors.toList());
        List<TableSpecialNumbers> fNumbers = specialNumbers.stream().filter(tableSpecialNumbers -> tableSpecialNumbers.getRegion_id() == 2).collect(Collectors.toList());
        List<TableSpecialNumbers> dNumbers = specialNumbers.stream().filter(tableSpecialNumbers -> tableSpecialNumbers.getRegion_id() == 3).collect(Collectors.toList());
        List<TableSpecialNumbers> sNumbers = specialNumbers.stream().filter(tableSpecialNumbers -> tableSpecialNumbers.getRegion_id() == 4).collect(Collectors.toList());
        if (inputDTO.getBelongTo().contains("K")) {
            SaveOrderOutputDTO kSpecialFilterResult = calcSpecialNumberLimit("K", inputDTO, kNumbers);
            if (kSpecialFilterResult != null) return kSpecialFilterResult;
        }
        if (inputDTO.getBelongTo().contains("F")) {
            SaveOrderOutputDTO fSpecialFilterResult = calcSpecialNumberLimit("F", inputDTO, fNumbers);
            if (fSpecialFilterResult != null) return fSpecialFilterResult;
        }
        if (inputDTO.getBelongTo().contains("D")) {
            SaveOrderOutputDTO dSpecialFilterResult = calcSpecialNumberLimit("D", inputDTO, dNumbers);
            if (dSpecialFilterResult != null) return dSpecialFilterResult;
        }
        if (inputDTO.getBelongTo().contains("S")) {
            SaveOrderOutputDTO sSpecialFilterResult = calcSpecialNumberLimit("S", inputDTO, sNumbers);
            if (sSpecialFilterResult != null) return sSpecialFilterResult;
        }

        //创建并添加orders记录;done
        TableOrders order = new TableOrders();
        order.setMachine_number(inputDTO.getMachine_number());
        order.setSerial_number(inputDTO.getSerialNumber());
        order.setBelong_to(inputDTO.getBelongTo());
        insertOrder(order, dt);
        //获取刚插入的订单记录的id作为接下来插入的betNumber的order_id
        List<OrdersAndBetNumbersDTO> pureOrdersBySerialNumber = orderService.getPureOrdersBySerialNumber(inputDTO.getSerialNumber());
        log.info("saveOrder(), pureOrdersBySerialNumber:{}", JSON.toJSON(pureOrdersBySerialNumber));
        if (pureOrdersBySerialNumber == null || pureOrdersBySerialNumber.size() < 1) {
            return new SaveOrderOutputDTO(600, "insert order failure!");
        }

        //创建并添加bet_numbers记录;done
        for (SaveOrderInputDTO.Bets bet : inputDTO.getBets()) {
            TableBetNumbers number = new TableBetNumbers();
            number.setOrder_id(pureOrdersBySerialNumber.get(0).getId());
            number.setBet_number(bet.getNum() + "");
            number.setIs_pool(bet.isPool() ? 1 : 0);
            number.setBet_money(bet.getMoney());
            insertBetNumber(number, dt);
        }

        //查询order&bet_number
        OrdersAndBetNumbersDTO ordersResult = orderService.getOrders("", "", inputDTO.getSerialNumber(), 0, null, null, null, null, null).get(0);
        log.info("saveOrder(), orderResult:{}", JSON.toJSON(ordersResult));
        return new SaveOrderOutputDTO(200, "success", ordersResult);
    }

    private double hasTotal = 0;//取当天number订单

    private SaveOrderOutputDTO calcSpecialNumberLimit(String area, SaveOrderInputDTO inputDTO, List<TableSpecialNumbers> numbers) {
        for (TableSpecialNumbers number : numbers) {

            hasTotal = 0;
            List<TableBetNumbers> betsByDate = orderService.getBetsByDate(DateUtils.getSub4Date() + " 00:00:00", DateUtils.getSub4Date() + " 23:59:59", number.getNumber());
            if (betsByDate != null && betsByDate.size() > 1) {
                hasTotal += betsByDate.stream().mapToDouble(TableBetNumbers::getBet_money).summaryStatistics().getSum();
            }

            Optional<SaveOrderInputDTO.Bets> first = inputDTO.getBets().stream().filter(bet -> {
                        tempExceeding = bet.getMoney() + hasTotal - number.getLimit();
                        return (bet.getNum() + "").equals(number.getNumber()) && ((bet.getMoney() + hasTotal) > number.getLimit());
                    }
            ).findFirst();
            if (first.isPresent()) return new SaveOrderOutputDTO(400, area + " area's specialNumber(" + number.getNumber() + ") exceeding the limit(" + number.getLimit() + "):" + (tempExceeding));
        }
        return null;
    }

    //添加orders记录;
    private void insertOrder(TableOrders order, String dt) {
        order.setIs_winner(0);
        order.setTotal_winning_amount(0);
        order.setIs_paid(0);
        order.setIs_deleted(0);
        log.info("insertOrder(), order:{}", JSON.toJSON(order));
        orderService.insertOrder(order, dt);
    }

    //添加bet_numbers记录;//1
    private void insertBetNumber(TableBetNumbers number, String dt) {
        log.info("insertBetNumber(), number:{}", JSON.toJSON(number));
        orderService.insertBetNumber(number, dt);
    }

    @PostMapping("getPureOrders")
    public List<OrdersAndBetNumbersDTO> getPureOrders() {
        String startTime = DateUtils.nowDate() + " 00:00:00";
        String endTime = DateUtils.nowDate() + " 23:59:59";
        return orderService.getPureOrders("", "", startTime, endTime);
    }

    //给app返回serial_number//2
    @PostMapping("getSerialNumber")
    public String getSerialNumber() {
        //orders今天条目数
//        String startTime = DateUtils.nowDate() + " 00:00:00";
//        String endTime = DateUtils.nowDate() + " 23:59:59";
//        log.info("getSerialNumber() time scope:{}-{}", startTime, endTime);
//        List<OrdersAndBetNumbersDTO> todayOrders = getPureOrders();
//        log.info("getSerialNumber() today orders:" + JSON.toJSONString(todayOrders));
//        return (todayOrders.size() + 1) + "";

        return String.valueOf(orderService.getPureOrdersByDate(DateUtils.nowDate()).size() + 1);


//        String serial_number = "";
//        try {
//            serial_number = orderService.getAllOrders().stream().max(Comparator.comparingLong(new ToLongFunction<TableOrders>() {
//                @Override
//                public long applyAsLong(TableOrders value) {
//                    return Long.parseLong(value.getSerial_number());
//                }
//            })).get().getSerial_number();
//        } catch (Exception e) {
//            return "";
//        }
//        return "" + (Long.parseLong(serial_number) + 1);
    }

    @PostMapping("appGetOrdersByDateRange")
    public AppGetOrdersByDateRangeOutputDTO appGetOrdersByDateRange(String machine_number, String startTime, String endTime) {
        AppGetOrdersByDateRangeOutputDTO outputDTO = new AppGetOrdersByDateRangeOutputDTO();
        List<AppGetOrdersByDateRangeOutputDTO.Orders> ordersList = new ArrayList<>();

        double commission = machineService.getMachines(machine_number).get(0).getCommission();

        OrdersOutputDTO orders = getOrders(null, machine_number, null, null, 1, 0, startTime, endTime, null, null, null, null);
        log.info("appGetOrdersByDateRange(), orders:{}", JSON.toJSON(orders));

        Map<String, List<OrdersAndBetNumbersDTO>> groupOrders = orders.getOrderList().stream().collect(Collectors.groupingBy(new Function<OrdersAndBetNumbersDTO, String>() {
            @Override
            public String apply(OrdersAndBetNumbersDTO ordersAndBetNumbersDTO) {
                String created_at = ordersAndBetNumbersDTO.getCreated_at();
                if (created_at == null || created_at.equals("")) {
                    return "";
                }
                return ordersAndBetNumbersDTO.getCreated_at().substring(0, 10);
            }
        }));
        log.info("appGetOrdersByDateRange(), groupOrders:{}", JSON.toJSON(groupOrders));

        groupOrders.forEach(new BiConsumer<String, List<OrdersAndBetNumbersDTO>>() {
            @Override
            public void accept(String s, List<OrdersAndBetNumbersDTO> ordersAndBetNumbersDTOS) {
                AppGetOrdersByDateRangeOutputDTO.Orders o = new AppGetOrdersByDateRangeOutputDTO.Orders();
                o.setMachine_number(machine_number);
                o.setDate(s);
                o.setCommission(commission);
                o.setBet_money(ordersAndBetNumbersDTOS.stream().mapToDouble(OrdersAndBetNumbersDTO::getBet_money).summaryStatistics().getSum());
                o.setPrizes(ordersAndBetNumbersDTOS.stream().mapToDouble(OrdersAndBetNumbersDTO::getPrizes).summaryStatistics().getSum());
                o.setRedemption_amount(ordersAndBetNumbersDTOS.stream().filter(ordersAndBetNumbersDTO -> ordersAndBetNumbersDTO.getIs_paid() == 1).mapToDouble(OrdersAndBetNumbersDTO::getPrizes).summaryStatistics().getSum());
                String belong_to = ordersAndBetNumbersDTOS.get(0).getBelong_to();
                int length = belong_to.split("\\+").length;
                o.setSub_total_bet_money(o.getBet_money() * length);
                ordersList.add(o);
            }
        });
        outputDTO.setOrders(ordersList);
        return outputDTO;
    }

    @PostMapping("getOrdersByDateRange")
    public AppGetOrdersByDateRangeOutputDTO getOrdersByDateRange(String machine_number, String startTime, String endTime) {
        log.info("getOrdersByDateRange(), machine_number:{}, startTime:{}, endTime:{}", machine_number, startTime, endTime);
        if (machine_number != null && !machine_number.equals("")) {
            return appGetOrdersByDateRange(machine_number, startTime, endTime);
        }


        AppGetOrdersByDateRangeOutputDTO outputDTO = new AppGetOrdersByDateRangeOutputDTO();
        List<AppGetOrdersByDateRangeOutputDTO.Orders> ordersList = new ArrayList<>();

        List<TableMachines> machines = machineService.getMachines("");
        for (TableMachines machine : machines) {
            AppGetOrdersByDateRangeOutputDTO list = appGetOrdersByDateRange(machine.getMachine_number(), startTime, endTime);
            ordersList.addAll(list.getOrders());
        }
        outputDTO.setOrders(ordersList);
        return outputDTO;
    }

    //号码统计
    @PostMapping("numberDistribute")
    public NumberDistributeOutputDTO numberDistribute(@RequestParam(name = "bet_number", required = false) String bet_number,
                                                      @RequestParam(name = "machine_number", required = false) String machine_number,
                                                      @RequestParam(name = "serial_number", required = false) String serial_number,
                                                      @RequestParam(name = "is_winner", required = false) Integer is_winner,
                                                      //分页
                                                      @RequestParam(name = "page", required = false, defaultValue = "0") int page,
                                                      @RequestParam(name = "pageSize", required = false, defaultValue = "0") int pageSize,
                                                      //日期
                                                      @RequestParam(name = "startTime", required = false) String startTime,
                                                      @RequestParam(name = "endTime", required = false) String endTime,
                                                      //地区
                                                      @RequestParam(name = "belong_to", required = false) String belong_to,
                                                      //是否今天1是今天
                                                      @RequestParam(name = "isToday", required = false) String isToday,
                                                      @RequestParam(name = "b_is_winner", required = false) String b_is_winner,
                                                      @RequestParam(name = "checked_winning", required = false) String checked_winning) {
        NumberDistributeOutputDTO output = new NumberDistributeOutputDTO();
        List<NumberDistributeOutputDTO.NumberData> numberDatas = new ArrayList<>();
        double total = 0;

        OrdersOutputDTO orders = getOrders(bet_number, machine_number, serial_number, is_winner, page, pageSize, startTime, endTime, belong_to, isToday, b_is_winner, checked_winning);
        output.setPageCount(orders.getPageCount());
        //按号码合并
        Map<String, List<OrdersAndBetNumbersDTO>> ordersByNumber = orders.getOrderList().parallelStream().collect(Collectors.groupingBy(dto -> dto.getBet_number(), Collectors.toList()));
        log.info("numberDistribute() ordersByNumber:{}", JSON.toJSONString(ordersByNumber));
        ordersByNumber.forEach(new BiConsumer<String, List<OrdersAndBetNumbersDTO>>() {
            @Override
            public void accept(String number, List<OrdersAndBetNumbersDTO> os) {

                NumberDistributeOutputDTO.NumberData dto = new NumberDistributeOutputDTO.NumberData();
                dto.setNumber(number);
                if (number.contains("P") || number.contains("p")) {
                    dto.setPool("POOL");
                    dto.setMoney("");
                } else {
                    dto.setPool("");
                    dto.setMoney(os.stream().filter(ordersAndBetNumbersDTO -> !ordersAndBetNumbersDTO.getBet_number().contains("P")).mapToDouble(OrdersAndBetNumbersDTO::getBet_money).summaryStatistics().getSum() + "");
                }

                //金额
                numberDatas.add(dto);
            }
        });
        output.setTotalMoney(numberDatas.stream().filter(new Predicate<NumberDistributeOutputDTO.NumberData>() {
            @Override
            public boolean test(NumberDistributeOutputDTO.NumberData numberData) {
                return !numberData.getNumber().contains("P");
            }
        }).mapToDouble(new ToDoubleFunction<NumberDistributeOutputDTO.NumberData>() {
            @Override
            public double applyAsDouble(NumberDistributeOutputDTO.NumberData value) {
                return Double.valueOf(value.getMoney());
            }
        }).summaryStatistics().getSum());
        output.setNumberDatas(numberDatas);
        output.setDataSize(numberDatas.size());
        return output;
    }
}
